/* ============================================================
 * Part of 'Autostop' project
 * Under GPL v2 license - http://www.gnu.org/licenses/gpl.html
 * (c) 2006 - Autostop team
 */

///\file fakecamera.h Qt-based, fake camera driver lib. Uses libcamera interface, supplies images from disk
/// Files are read in alphabetical order from directory, which name is read from
/// AUTOSTOP_FAKEFILES_PATH environment variable. PNG files are used as camre input, JPG2K files
/// are used to create sequence. Images from camera are supplied are fake rate of 20fps
/// Files are read on camera_init, and then supplied from memory-buffer.

#include <stdlib.h>

#include <QList>
#include <QFileInfo>
#include <QDir>
#include <QImage>

#include "camera.h"

// =================================
// constants
#define ENV_FILES_PATH	"AUTOSTOP_FAKEFILES_PATH"	///< env variable contaning the path to files
#define FALLBACK_PATH	"/autostop/fakeimages"		///< fallback path

// =================================
// globals
QList<QFileInfo>	Images;					///< Camera images
QList<QFileInfo>	Sequence;				///< Sequence images (jp2)
QList<QFileInfo>::iterator	ImagesIterator;	///< Current image read from camera

QString				ErrorMsg	= "No error";	///< Error message buffer

// ========================================================
int camera_init(void)
{
	// get path
	const char* path = getenv( ENV_FILES_PATH );
	if ( path == 0 )
	{
		path = FALLBACK_PATH;
	}
	// read images
	QDir dir( path );

	//check
	if ( ! dir.exists() )
	{
		//qDebug( "directory %s does not exists!", path );
		ErrorMsg = QString( "directory %1 does not exists!" ).arg( path );
		return CAMERA_ERROR;
	}

	// prepare name filters
	QStringList imageFilters, sequenceFilters;
	imageFilters << "*.png" << "*.PNG";
	sequenceFilters << "*.jp2" << "*.JP2";

	// get image list
	Images		= dir.entryInfoList( imageFilters );
	Sequence	= dir.entryInfoList( sequenceFilters );

	// check image list
	if ( Images.count() == 0 )
	{
		//qDebug("No images in %s", path );
		ErrorMsg = QString( "No images in %1" ).arg( path );
		return CAMERA_ERROR;
	}

	// reset iterator
	ImagesIterator = Images.begin();
	
	return CAMERA_OK;
}

// ========================================================
int camera_image_width(void)
{
	return 640;
}

// ========================================================
int camera_image_height(void)
{
	return 480;
}

// ========================================================
int camera_get_image( uint8_t* pbuffer, size_t bufsize, uint64_t* ptimestamp )
{
	Q_UNUSED( ptimestamp );
	
	if ( ImagesIterator != Images.end() )
	{
		QFileInfo fileInfo = *ImagesIterator;
		// read from file
		QImage image;
		if ( ! image.load( fileInfo.absoluteFilePath() ) )
		{
			ErrorMsg = "Could not read image";
			return CAMERA_ERROR;
		}
		
		qDebug("Supplying frame from image: %s", qPrintable( fileInfo.baseName() ) );
		
		// copy to buffer
		uint8_t* p = pbuffer;
		int w = camera_image_width();
		int h = camera_image_height();
		
		for( int y = 0; y < h; y++ )
		{
			for( int x = 0; x < w; x++ )
			{
				// check buffer size
				if ( p < pbuffer + bufsize )
				{
					// check imgae size vs declared image size
					if ( y < image.height() && x < image.width() )
					{
						QRgb pixel = image.pixel( x, y );
						*p = qGray( pixel );
					}
					else
					{
						*p = 0;
					}
					
					p++;
				}
				else
				{
					break;
				}
			}// x
		}// y
		
		// get next image
		ImagesIterator ++;
		
		return CAMERA_OK;
	}
	ErrorMsg = "Fake camera: out of images";
	return CAMERA_EOF;
}

// ========================================================
sequence_t camera_open_sequence(void)
{
	return SEQUENCE_INVALID;
}

// ========================================================
int camera_read_sequence( sequence_t sequence, uint8_t* pbuffer, size_t bufsize )
{
	Q_UNUSED( sequence );
	Q_UNUSED( pbuffer );
	Q_UNUSED( bufsize );
	
	return CAMERA_ERROR;
}

// ========================================================
void camera_close_sequence( sequence_t sequence )
{
	Q_UNUSED( sequence );
	// nothing
}

// ========================================================
const char* camera_error_message()
{
	return (const char*)ErrorMsg.toUtf8();
}
